package com.gw.smscheck.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gw.smscheck.entity.business.positionInfo.PositionNow;
import com.gw.smscheck.service.business.positionInfo.PositionNowService;
import org.springframework.beans.factory.annotation.Autowired;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: smscheck
 * @description: 判断多人或单人是否在指定区域
 * @author: jiangbo
 * @create: 2018-11-06 14:07
 */
public class MapUtil {
    @Autowired
    private PositionNowService positionNowService;

    /**
     * 传入区域，判断多个人的标注是否在区域，返回在区域内的人员
     */
    public static List<PositionNow> isPtInPolyMany(String strJson, List<PositionNow> positionNowList) {
        //区域的坐标区域
        List<Point2D.Double> pts = new ArrayList<>();
        String[] strArray = strJson.split(";");
        for (String str : strArray) {
            String[] strPoint = str.split(",");
            pts.add(new Point2D.Double(Double.parseDouble(strPoint[0]), Double.parseDouble(strPoint[1])));
        }
        int N = pts.size();
        //定义返回的信息
        List<Point2D.Double> returnList = new ArrayList<>();//返回的坐标
        List<PositionNow> returnListNowList = new ArrayList<>();
        //循环判断人员是否在区域之内
        for (PositionNow obj : positionNowList) {
            Point2D.Double point = new Point2D.Double(obj.getLng(), obj.getLat());
            boolean boundOrVertex = true; // 如果点位于多边形的顶点或边上，也算做点在多边形内，直接返回true
            int intersectCount = 0; // cross points count of x
            double precision = 2e-10; // 浮点类型计算时候与0比较时候的容差
            Point2D.Double p1, p2; // neighbour bound vertices
            Point2D.Double p = point; // 当前点
            p1 = pts.get(0); // left vertex
            for (int i = 1; i <= N; ++i) { // check all rays
                if (p.equals(p1)) {
                    returnList.add(p);
                    returnListNowList.add(obj);
                }

                p2 = pts.get(i % N); // right vertex
                if (p.x < Math.min(p1.x, p2.x)
                        || p.x > Math.max(p1.x, p2.x)) { // ray is outside of our interests
                    p1 = p2;
                    continue; // next ray left point
                }

                if (p.x > Math.min(p1.x, p2.x)
                        && p.x
                        < Math.max(p1.x, p2.x)) { // ray is crossing over by the algorithm (common part of)
                    if (p.y <= Math.max(p1.y, p2.y)) { // x is before of ray
                        if (p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)) { // overlies on a horizontal ray
                            returnList.add(p);
                            returnListNowList.add(obj);
                        }

                        if (p1.y == p2.y) { // ray is vertical
                            if (p1.y == p.y) { // overlies on a vertical ray
                                returnList.add(p);
                                returnListNowList.add(obj);
                            } else { // before ray
                                ++intersectCount;
                            }
                        } else { // cross point on the left side
                            double xinters =
                                    (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y; // cross point of y
                            if (Math.abs(p.y - xinters) < precision) { // overlies on a ray
                                returnList.add(p);
                                returnListNowList.add(obj);
                            }

                            if (p.y < xinters) { // before ray
                                ++intersectCount;
                            }
                        }
                    }
                } else { // special case when ray is crossing through the vertex
                    if (p.x == p2.x && p.y <= p2.y) { // p crossing over p2
                        Point2D.Double p3 = pts.get((i + 1) % N); // next vertex
                        if (p.x >= Math.min(p1.x, p3.x)
                                && p.x <= Math.max(p1.x, p3.x)) { // p.x lies between p1.x & p3.x
                            ++intersectCount;
                        } else {
                            intersectCount += 2;
                        }
                    }
                }
                p1 = p2; // next ray left point
            }


            if (intersectCount % 2 == 0) { // 偶数在多边形外

            } else { // 奇数在多边形内
                returnList.add(p);
                returnListNowList.add(obj);
            }
        }
        //直接返回在区域内的重点人员
        return returnListNowList;
    }

    /**
     * 传入区域，判断单个人是否在区域，返回true/false
     */
    public static boolean isPtInPoly(String strJson, PositionNow obj) {
        boolean isPresence=false;
        //区域的坐标区域
        List<Point2D.Double> pts = new ArrayList<>();
        String[] strArray = strJson.split(";");
        for (String str : strArray) {
            String[] strPoint = str.split(",");
            pts.add(new Point2D.Double(Double.parseDouble(strPoint[0]), Double.parseDouble(strPoint[1])));
        }
        int N = pts.size();

        //判断人员是否在区域之内

        Point2D.Double point = new Point2D.Double(obj.getLng(), obj.getLat());
        boolean boundOrVertex = true; // 如果点位于多边形的顶点或边上，也算做点在多边形内，直接返回true
        int intersectCount = 0; // cross points count of x
        double precision = 2e-10; // 浮点类型计算时候与0比较时候的容差
        Point2D.Double p1, p2; // neighbour bound vertices
        Point2D.Double p = point; // 当前点
        p1 = pts.get(0); // left vertex
        for (int i = 1; i <= N; ++i) { // check all rays
            if (p.equals(p1)) {
                isPresence=true;
            }

            p2 = pts.get(i % N); // right vertex
            if (p.x < Math.min(p1.x, p2.x)
                    || p.x > Math.max(p1.x, p2.x)) { // ray is outside of our interests
                p1 = p2;
                continue; // next ray left point
            }

            if (p.x > Math.min(p1.x, p2.x)
                    && p.x
                    < Math.max(p1.x, p2.x)) { // ray is crossing over by the algorithm (common part of)
                if (p.y <= Math.max(p1.y, p2.y)) { // x is before of ray
                    if (p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)) { // overlies on a horizontal ray
                        isPresence=true;
                    }

                    if (p1.y == p2.y) { // ray is vertical
                        if (p1.y == p.y) { // overlies on a vertical ray
                            isPresence=true;
                        } else { // before ray
                            ++intersectCount;
                        }
                    } else { // cross point on the left side
                        double xinters =
                                (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y; // cross point of y
                        if (Math.abs(p.y - xinters) < precision) { // overlies on a ray
                            isPresence=true;
                        }

                        if (p.y < xinters) { // before ray
                            ++intersectCount;
                        }
                    }
                }
            } else { // special case when ray is crossing through the vertex
                if (p.x == p2.x && p.y <= p2.y) { // p crossing over p2
                    Point2D.Double p3 = pts.get((i + 1) % N); // next vertex
                    if (p.x >= Math.min(p1.x, p3.x)
                            && p.x <= Math.max(p1.x, p3.x)) { // p.x lies between p1.x & p3.x
                        ++intersectCount;
                    } else {
                        intersectCount += 2;
                    }
                }
            }
            p1 = p2; // next ray left point
        }
        if (intersectCount % 2 == 0) { // 偶数在多边形外
        } else { // 奇数在多边形内
            isPresence=true;
        }
        //直接是否在区域
        return isPresence;
    }

    /**
     * @Description: 页面获取到区域，转换成字符串
     * @Param:
     * @return:
     * @Author: jiangbo
     * @Date: 2018/11/6 0006
     */
    public static String getPathString(String str) {
        String strReturn = "";
        JSONArray jsonArray = JSON.parseArray(str);
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject json = JSON.parseObject(jsonArray.getString(i));
            strReturn += json.getString("lng") + "," + json.getString("lat") + ";";
        }
        return strReturn;
    }

    /**
     * 传入经纬度判断
     * @param strJson
     * @param lng
     * @param lat
     * @return
     */
    public static boolean isPtInPoly(String strJson,Double lng,Double lat) {
        PositionNow obj = new PositionNow();
        obj.setLng(lng);
        obj.setLat(lat);
        return isPtInPoly(strJson,obj);
    }
/** 
* @Description:
* @Param:  
* @return:  
* @Author: jiangbo
* @Date: 2018/11/9 0009 
*/ 
    public static double getDistance(double lat_a, double lng_a, double lat_b, double lng_b){
        double pk = 180 / 3.14169;
        double a1 = lat_a / pk;
        double a2 = lng_a / pk;
        double b1 = lat_b / pk;
        double b2 = lng_b / pk;
        double t1 = Math.cos(a1) * Math.cos(a2) * Math.cos(b1) * Math.cos(b2);
        double t2 = Math.cos(a1) * Math.sin(a2) * Math.cos(b1) * Math.sin(b2);
        double t3 = Math.sin(a1) * Math.sin(b1);
        double tt = Math.acos(t1 + t2 + t3);
        return 6371000 * tt;
    }

}
